package express.compiler;

import express.bttree.*;
import org.apache.commons.lang3.StringUtils;

import java.util.List;

public class ExprUtils {


    public static Node toBtTree(SyntaxNode parent, Class<? extends OpNode> klass) {
        if(parent.getType() == SyntaxNodeType.Nodes) {
            List<SyntaxNode> childNodes = parent.getChildNodes();
            if(childNodes.size() > 1) {
                SyntaxNode opNode = childNodes.get(1);
                Node node;
                if(opNode.getType() == SyntaxNodeType.Or) {
                    node = new OrNode();
                } else if(opNode.getType() == SyntaxNodeType.And) {
                    node = new AndNode();
                } else {
                    throw new RuntimeException("不能处理该节点，" + opNode.getType());
                }
                for (SyntaxNode childNode : childNodes) {
                    if(childNode.getType() != SyntaxNodeType.Or && childNode.getType() != SyntaxNodeType.And) {
                        node.getChildren().add(toBtTree(childNode, klass));
                    }
                }
                return node;
            } else {
                return toBtTree(childNodes.get(0), klass);
            }
        } else if(parent.getType() == SyntaxNodeType.Expr) {
            MethodInfo methodInfo = MethodInfo.convert(parent.getChildNodes());
            //System.err.println(methodInfo);

            try {
                OpNode opNode = klass.newInstance();
                opNode.setMethod(methodInfo.getMethodName());
                opNode.setParams(methodInfo.getParams());
                opNode.setOp(methodInfo.getOp());
                opNode.setValue(methodInfo.getResult());
                return opNode;
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        } else {
            throw new RuntimeException("不处理该节点，" + parent.getType());
        }
    }

    public static Node convert(String scriptExpr, Class<? extends OpNode> klass) {
        Tokenizer tokenizer = new Tokenizer(scriptExpr);
        List<String> tokens = tokenizer.tokenizer();
        System.out.println(tokens);
        Parser parser = new Parser(tokens);
        SyntaxNode syntaxNode = parser.parse();
        //System.err.println(JSON.toJSONString(syntaxNode,true));
        Node btNode = toBtTree(syntaxNode,klass);
        return btNode;
    }

    private static int arithmetic0( SyntaxNode parent ) {
        if(parent.getType() == SyntaxNodeType.Nodes) {
            List<SyntaxNode> childNodes = parent.getChildNodes();
            if(childNodes.size() > 1) {
                int value = 0;
                String op = "";
                for (SyntaxNode childNode : childNodes) {
                    if(childNode.getType() == SyntaxNodeType.And || childNode.getType() == SyntaxNodeType.Or) {
                        op = childNode.getValue();
                        continue;
                    }
                    int nodeValue = arithmetic0(childNode);
                    if(StringUtils.isBlank(op)) {
                        value = nodeValue;
                    } else {
                        switch (op) {
                            case "+":
                                value += nodeValue;
                                break;
                            case "-":
                                value -= nodeValue;
                                break;
                            case "*":
                                value *= nodeValue;
                                break;
                            case "/":
                                value /= (float)nodeValue;
                                break;
                            default:
                                throw new RuntimeException("不处理该节点");
                        }
                    }
                }

                return value;

            } else {
                return arithmetic0(childNodes.get(0));
            }
        } else if(parent.getType() == SyntaxNodeType.Expr) {
            return Integer.parseInt( parent.getChildNodes().get(0).getValue() );
        } else {
            throw new RuntimeException("不处理该节点，" + parent.getType());
        }
    }

    public static int arithmetic(String expr) {
        Tokenizer tokenizer = new Tokenizer(expr);
        List<String> tokens = tokenizer.tokenizer();
        Parser ecParser = new Parser(tokens);
        SyntaxNode resultNode = ecParser.parse();
        //System.err.println(JSON.toJSONString(resultNode,true));
        return arithmetic0(resultNode);
    }
}

